#include "Game/MovingBlock.h"

namespace PocketSurvival
{
    void MovingBlockSet::updateBox()
    {
        Point3 point, point2;
        bool hasValue;

        MovingBlocksMutex.lock();
        for(MovingBlock &block : Blocks)
        {
            point = (hasValue ? Point3(MathUtils::Min(point.posX, block.offset.posX), MathUtils::Min(point.posY, block.offset.posY), MathUtils::Min(point.posZ, block.offset.posZ)) : block.offset);
            point2 = (hasValue ? Point3(MathUtils::Max(point2.posX, block.offset.posX), MathUtils::Max(point2.posY, block.offset.posY), MathUtils::Max(point2.posZ, block.offset.posZ)) : block.offset);
            hasValue = true;
        }
        MovingBlocksMutex.unlock();

        if(hasValue)
        {
            MovingBox.Left = point.posX;
            MovingBox.Top = point.posY;
            MovingBox.Near = point.posZ;

            MovingBox.Width = point2.posX - point.posX + 1;
            MovingBox.Height = point2.posY - point.posY + 1;
            MovingBox.Depth = point2.posZ - point.posZ + 1;
        }
    }

    BoundingBox MovingBlockSet::getBoundingBox(bool extendToFillCells)
    {
        Vector3 min(Position.posX + (float)MovingBox.Left, Position.posY + (float)MovingBox.Top, Position.posZ + (float)MovingBox.Near);
        Vector3 max(Position.posX + (float)MovingBox.getRight(), Position.posY + (float)MovingBox.getBottom(), Position.posZ + (float)MovingBox.getFar());
        if(extendToFillCells)
        {
            min.posX = MathUtils::Floor(min.posX);
            min.posY = MathUtils::Floor(min.posY);
            min.posZ = MathUtils::Floor(min.posZ);
            max.posX = MathUtils::Ceil(max.posX);
            max.posY = MathUtils::Ceil(max.posY);
            max.posZ = MathUtils::Ceil(max.posZ);
        }
        return BoundingBox(min, max);
    }

    void MovingBlockSet::setBlock(const Point3 &offset, int32_t value)
    {
        MovingBlocksMutex.lock();

        FIND_START:
        for(auto it = Blocks.begin(); it != Blocks.end(); ++it)
        {
            if(it->offset == offset)
            {
                Blocks.erase(it);
                goto FIND_START;
            }
        }
        if(value != 0)
        {
            Blocks.emplace_back(offset, value);
        }
        MovingBlocksMutex.unlock();
        updateBox();
    }
}